<template>
  <el-date-picker v-model="pickDate" style="position: absolute;top: 0;left: 200px;" size="large" value-format="YYYY-MM-DD" :clearable="false" />
  <div class="orderFullCBox">
    <!-- width:calc( `${siteList.length}`*180px ) style="width:1700px;"-->
    <div :style="calendarWidth">
      <FullCalendar ref="fullCalendar" :options="calendarOptions" class="orderFullC">
        <template #eventContent="arg">
          <div class="eventBox">
            <!-- <b>{{ arg.timeText }}</b> -->
            <p v-if="arg.event.extendedProps.data">{{ arg.event.extendedProps.data.orderName }}</p>
            <p v-if="arg.event.extendedProps.data">{{ arg.event.extendedProps.data.orderTelno }}</p>
            <p v-if="arg.event.extendedProps.data&&arg.event.extendedProps.data.orderType!='3'">{{ arg.event.title }}</p>
            <p v-if="arg.event.extendedProps.isNew">{{ arg.event.title }}</p>
          </div>
        </template>
      </FullCalendar>
    </div>
  </div>
</template>

<script setup>
import FullCalendar from '@fullcalendar/vue3'
import dayGridPlugin from '@fullcalendar/daygrid'
import timeGridPlugin from '@fullcalendar/timegrid'
import resourceTimeGridPlugin from '@fullcalendar/resource-timegrid'
import interactionPlugin from '@fullcalendar/interaction'
import listPlugin from '@fullcalendar/list'
import { toRefs } from '@vueuse/shared'
import { getCurrentInstance, onMounted, reactive } from '@vue/runtime-core'
import { getSiteList } from '../../../../../api/ven'
import useVenStore from '../../../../../store/modules/ven'
import { dayjs } from 'element-plus'
import { getGenerdatePrice, getReserveList } from '../../../../../api/ven/reserve'
import { watch } from 'vue'

const venStore = useVenStore()
const currProject = _.find(venStore.projectList, p => p.id === props.projectId)
let slotDuration = '00:30:00'
if (currProject.halfHourAllow == '1') {
  slotDuration = '00:30:00'
} else {
  slotDuration = '00:60:00'
}
const { proxy } = getCurrentInstance()
const emit = defineEmits(['selectedPosition', 'selectedOrder'])

const props = defineProps({
  projectId: {
    type: String,
    default: null,
    required: true
  },
  initialDate: {
    type: String,
    default: () => dayjs().format('YYYY-MM-DD')
  }
})
const data = reactive({
  calendarWidth: '',
  calendarOptions: {
    plugins: [
      dayGridPlugin,
      timeGridPlugin,
      interactionPlugin, // needed for dateClick
      resourceTimeGridPlugin,
      listPlugin
    ],
    headerToolbar: {
      left: 'prev today next',
      center: '',
      right: ''
    },
    customButtons: {
      prev: {
        click: () => handleChangeDay(-1)
      },
      next: {
        click: () => handleChangeDay(1)
      },
      today: {
        text: '今天',
        click: handleToday
      }
    },
    initialDate: props.initialDate,
    // resources: [],
    // events: [],
    locale: 'zh-cn',
    initialView: 'resourceTimeGridDay',
    slotLabelFormat: {
      hour: '2-digit',
      minute: '2-digit',
      meridiem: false,
      hour12: false // 设置时间为24小时
    },
    handleWindowResize: false,
    height: '80vh',
    allDaySlot: false,
    // slotMinTime: venStore.businessPeriod[0], // 设置显示的时间从几点开始
    // slotMaxTime: venStore.businessPeriod[1], // 设置显示的时间从几点结束
    slotMinTime: currProject.businessStart, // 设置显示的时间从几点开始
    slotMaxTime: currProject.businessEnd, // 设置显示的时间从几点结束
    slotDuration: slotDuration,
    // `$(currProject.halfHourAllow) == '1'? '00:30:00':'00:60:00'`
    editable: false, // 是否可以进行（拖动、缩放）修改
    selectable: true,
    unselectAuto: true,
    selectMirror: true,
    dayMaxEvents: true,
    slotLaneDidMount: item => {
      item.el.style.opacity = 0.5
      elTimeList.push({
        time: item.time.milliseconds,
        el: item.el
      })
    },
    select: handleDateSelect,
    eventClick: handleEventClick
  },
  pickDate: props.initialDate,
  positionList: []
})
const { calendarWidth, calendarOptions, pickDate, positionList } = toRefs(data)

// 0 过期预定 1 线下已付 2 线下未付 3 线上预定 4 人工锁场 5 固定已付 6 固定未付  预留
const colorArr = ['#D2D7D9', '#1EC886', '#F83E47', '#20ccca', '#e1e943', '#FEA64B', '#A570E9', '#f6c07a']
const elTimeList = [] // 日历的行
let siteList = []

let calendarApi = null
let selectedOrder = {}

const getCalendarApi = () => {
  if (!calendarApi) {
    calendarApi = proxy.$refs.fullCalendar.getApi()
  }
  return calendarApi
}

watch(() => positionList.value.length, val => {
  emit('selectedPosition', positionList.value)
}
)

/**
 * 根据时间设置是否可以预约
 */
const setBgColor = day => {
  const dayTime = dayjs(day).valueOf()
  let now
  if (currProject.halfHourAllow == '1') {
    now = dayjs().add(-30, 'minute').valueOf()
  } else {
    now = dayjs().add(-60, 'minute').valueOf()
  }
  _.each(elTimeList, obj => {
    obj.el.bgColor = ''
    if (dayTime + obj.time < now) {
      obj.el.bgColor = '#f0f0f0'
    }
  })
}

onMounted(() => {
  getSiteList({
    projectId: props.projectId,
    status: '1'
  }).then(res => {
    siteList = res.rows
    calendarWidth.value = `width:calc(${siteList.length} * 150px)`
    _.each(siteList, s => {
      let minReserveTimeStr = ''
      switch (s.minReserveTime) {
        case '0':
          s.minRes = 0.5
          minReserveTimeStr = '半小时'
          break
        case '1':
          s.minRes = 1
          minReserveTimeStr = '一小时'
          break
        case '2':
          s.minRes = 2
          minReserveTimeStr = '两小时'
          break
      }
      s.minReserveTimeStr = minReserveTimeStr

      getCalendarApi().addResource({
        id: s.id,
        title: `${s.name}`
        // title: `${s.name}（${minReserveTimeStr}起订）`
      })
    })
  })
    .then(() => {
      watch(pickDate, val => {
              if (val) {
                getCalendarApi().gotoDate(val)
          refreshData()
          setBgColor(val)
        }
            },
            { immediate: true }
      )
    })
})

function handleChangeDay(num) {
  pickDate.value = dayjs(pickDate.value)
    .add(num, 'day')
    .format('YYYY-MM-DD')
}

function handleToday() {
  pickDate.value = dayjs().format('YYYY-MM-DD')
}

/**
 * 判断当前时间段是否不可以预约
 */
const checkCannotReserve = (siteId, startTimeVal, endTimeVal) => {
  return _.some(getCalendarApi().getEvents(), e => {
    if (e.extendedProps.siteId !== siteId) {
      return
    }

    const eStartVal = dayjs(e.start).valueOf()
    const eEndVal = dayjs(e.end).valueOf()
    if (eStartVal >= startTimeVal && eStartVal < endTimeVal) {
      return true
    }
    if (eEndVal > startTimeVal && eEndVal <= endTimeVal) {
      return true
    }
    if (startTimeVal >= eStartVal && startTimeVal < eEndVal) {
      return true
    }
    if (endTimeVal > eStartVal && endTimeVal <= eEndVal) {
      return true
    }
  })
}

function handleDateSelect(selectInfo) {
  emit('selectedOrder', {})

  // console.log(selectInfo)

  const tempApi = selectInfo.view.calendar
  tempApi.unselect()

  const startTime = dayjs(selectInfo.start)
  let now
  if (currProject.halfHourAllow == '1') {
    now = dayjs()
      .add(-30, 'minute')
      .valueOf()
  } else {
    now = dayjs()
      .add(-60, 'minute')
      .valueOf()
  }

  if (startTime.valueOf() < now) {
    proxy.$modal.msgError('该时间段不可预约')
    return
  }

  const endTime = dayjs(selectInfo.end)
  const startHour = startTime.hour() + (startTime.minute() > 0 ? 0.5 : 0)
  const endHour = endTime.hour() + (endTime.minute() > 0 ? 0.5 : 0)
  const diff = endHour - startHour
  const startTimeVal = startTime.valueOf()
  const endTimeVal = endTime.valueOf()

  const currSite = _.find(siteList, s => {
    return s.id == selectInfo.resource.id
  })

  // 当前场地
  let cannotReserve = checkCannotReserve(currSite.id, startTimeVal, endTimeVal)
  if (cannotReserve) {
    proxy.$modal.msgError('该时间段不可预约')
    return
  }

  // 是父级场地找对应的子场地
  if (currSite.parentId == 0) {
    const childSites = _.filter(siteList, s => {
      return s.parentId == currSite.id
    })
    if (childSites.length > 0) {
      _.each(childSites, s => {
        if (!cannotReserve) {
          if (checkCannotReserve(s.id, startTimeVal, endTimeVal)) {
            cannotReserve = true
          }
        }
      })
    }
  }
  // 是子场地找对应的父级场地
  else {
    const parentSite = _.find(siteList, s => {
      return s.id == currSite.parentId
    })
    cannotReserve = checkCannotReserve(parentSite.id, startTimeVal, endTimeVal)
  }

  if (cannotReserve) {
    proxy.$modal.msgError('该时间段不可预约')
    return
  }

  if (diff < currSite.minRes) {
    proxy.$modal.msgError(`${currSite.minReserveTimeStr}起订`)
    return
  }
  if (currSite.halfHourAllow == '0' && diff % 1 !== 0) {
    proxy.$modal.msgError('预约最小单位为 1 小时')
    return
  }

  const position = {
    siteId: currSite.id,
    siteName: currSite.name,
    start: selectInfo.start,
    end: selectInfo.end,
    orderDate: startTime.format('YYYY-MM-DD'),
    orderTime: [startTime.format('HH:mm'), endTime.format('HH:mm')].join(',')
  }
  getGenerdatePrice([position]).then(res => {
    tempApi.addEvent({
      isNew: true,
      title: `￥${res.data[0][0]}`,
      resourceId: currSite.id,
      siteId: currSite.id,
      siteName: currSite.name,
      start: selectInfo.startStr,
      end: selectInfo.endStr
    })

    position.price = res.data
    positionList.value.push(position)
  })
}

function handleEventClick(clickInfo) {
  selectedOrder = {}
  // 未提交的预定可以删除
  if (clickInfo.event.extendedProps.isNew) {
    const startTime = dayjs(clickInfo.event.start)
    const endTime = dayjs(clickInfo.event.end)
    const title = `确定取消 ${clickInfo.event.extendedProps.siteName} ${pickDate.value} 时间段 ${startTime.format('HH:mm')}~${endTime.format('HH:mm')} 的预约？`
    const startTimeVal = startTime.valueOf()
    const endTimeVal = endTime.valueOf()
    proxy.$modal.confirm(title).then(function() {
      _.remove(positionList.value, p => {
        if (p.siteId === clickInfo.event.extendedProps.siteId) {
          if (startTimeVal === dayjs(p.start).valueOf() && endTimeVal === dayjs(p.end).valueOf()) {
            return true
          }
        }
      })

      clickInfo.event.remove()
    })
  }
  // 已提交的预定
  else {
    selectedOrder = clickInfo.event.extendedProps.data
  }

  emit('selectedOrder', selectedOrder)
}

/**
 * 把刚产生的预约设置的待定状态
 */
const undetermined = () => {
  positionList.value = []
  _.each(getCalendarApi().getEvents(), e => {
    if (e.extendedProps.isNew) {
      e.setExtendedProp('isNew', false)
      e.setProp('color', '#66b1ff')
    }
  })

  setTimeout(refreshData, 1000)
}

/**
 * 获取事件列表
 */
function refreshData(clearAll) {
  if (clearAll) {
    // 把刚产生的预约设置的待定状态
    undetermined()
  } else {
    _.each(getCalendarApi().getEvents(), e => {
      if (!e.extendedProps.isNew) {
        e.remove()
      }
    })

    getReserveList({
      projectId: props.projectId,
      orderDate: pickDate.value
    }).then(res => {
      _.each(siteList, s => {
        _.each(res.data[s.id], o => {
          getCalendarApi().addEvent({
            title: `￥${o.orderAmount}`,
            orderName: o.orderName,
            orderTelno: o.orderTelno,
            resourceId: o.siteId,
            start: dayjs(`${o.orderDate} ${o.orderTimePeriod.split(',')[0]}`).toDate(),
            end: dayjs(`${o.orderDate} ${o.orderTimePeriod.split(',')[1]}`).toDate(),
            color: colorArr[o.type],
            siteId: s.id,
            siteName: s.name,
            data: o
          })
        })
      })
    })
  }
}

function cancelOrder() {
  positionList.value = []
  _.each(getCalendarApi().getEvents(), e => {
    if (e.extendedProps.isNew) {
      e.remove()
    }
  })
}

defineExpose({
  refreshData,
  cancelOrder
})
</script>

<style lang="scss" scoped>
.eventBox {
	text-align: center;
	display: table-cell;
	font-size: 14px;
	vertical-align: middle;

	p {
		text-overflow: ellipsis;
		white-space: nowrap;
		overflow: hidden;
		width: 120px;
		margin: auto;
	}
}
.orderFullCBox {
	overflow: auto;
	width: 100%;
}
</style>
